<?php
/**
 * 传统的(非PDO方式)MYSQL数据源,提供MYSQL数据库访问能力
 * @author Leo 2010-09-07
 *
 */
uses ( 'mvc/model/datasources/postgresql/PostgresqlResultSet.inc' );

class PostgresqlDatasource extends DataSource implements IIocAware {
	private $trans = 0; //事务标志
	private $prefix = '';
	private $result = null;
	/**
	 * @param unknown_type $ioc
	 */
	public function afterCreated($ioc) {
		$this->connect ();
		$this->encoding ( $this->encoding );
	}
	/**
	 * @param unknown_type $ioc
	 */
	public function beforeDespose($ioc) {
		$this->discounect ();
	}
	
	/**
	 * 开始事务
	 * @return boolean 事务是否开始成功
	 */
	public function begin() {
		if ($this->trans === 1) { //已经在事务中
			return true;
		} else {
			if (@pg_query ( $this->connection, "BEGIN" ) === true) {
				$this->trans = 1;
				return true;
			} else {
				$msg = @pg_last_error ( $this->connection );
				$this->error_msg = "Unable to begin a transaction,server messages:[$msg]";
				return false;
			}
		}
	}
	
	/**
	 * 提交事务
	 * @return boolean 提交是否成功
	 */
	public function commit() {
		if ($this->trans === 0) { //不在事务中
			return true;
		} else {
			if (@pg_query ( $this->connection, "COMMIT" ) === true) {
				$this->trans = 0;
				return true;
			} else {
				$msg = @pg_last_error ( $this->connection );
				$this->error_msg = "Unable to commit current transaction,server messages:[$msg]";
				return false;
			}
		}
	}
	
	/**
	 * 连接数据库
	 * @return boolean 成功返回true,失败返回false
	 */
	public function connect() {
		if (! extension_loaded ( 'pgsql' )) {
			trigger_error ( '[' . WEBSITE . '] the pgsql extension is not installed.' , E_USER_ERROR );
			exit();
		}
		$this->options = array_merge ( array ('encoding' => 'UTF-8', 'prefix' => '', 'host' => 'localhost', 'user' => 'postgres', 'dbname' => 'postgres', 'password' => 'root', 'pconnect' => false ), $this->options );
		extract ( $this->options );
		$crash = 0;
		$this->prefix = isset ( $prefix ) ? $prefix : '';
		$this->encoding = isset ( $encoding ) && ! empty ( $encoding ) ? $encoding : 'UTF8';
		$c_str_ary = array ();
		foreach ( $this->options as $op => $val ) {
			if (in_array ( $op, array ('host', 'post', 'dbname', 'port', 'user', 'password' ) )) {
				$c_str_ary [] = $op . '=' . $val;
			}
		}
		$c_str = join ( ' ', $c_str_ary );
		if ($pconnect === true) {
			$this->connection = @pg_pconnect ( $c_str ) or $crash = 1;
		} else {
			$this->connection = @pg_connect ( $c_str ) or $crash = 1;
		}
		if ($crash == 1) {
			$msg = @pg_last_error ();
			$this->error_msg = "Unable to connect to MySQL server '$host' - Either your username, password are incorrect or you have not started POSTGRESQL on your server![$msg]";
			return false;
		}
		return true;
	}
	/**
	 * 断开与数据库的连接
	 */
	public function discounect() {
		if ($this->connection) {
			@pg_close ( $this->connection );
		}
	}
	/**
	 * 设置连接字符编码
	 * @param string $encoding 编码
	 */
	public function encoding($encoding) {
		if (! empty ( $encoding ) && ! is_numeric ( $encoding ) && $this->connection) {
			@pg_set_client_encoding ( $this->connection, $encoding );
			@pg_query ( $this->connection, "SET NAMES '{$encoding}'" );
			$this->encoding = $encoding;
		}
	}
	/**
	 * 转义字字符
	 * @param string $str 要转义的字符
	 * @return	string 已经转义的字符
	 */
	public function escape($str) {
		return pg_escape_string ( $this->connection, $str );
	}
	
	/**
	 * 执行非查询SQL语句
	 * @param string $sql 要执行的SQL语句
	 * @return int 操作影响的行数
	 */
	public function execute($sql) {
		$sql = str_replace ( '`', '"', $sql );
		$crase = 0;
		$this->result = @pg_query ( $this->connection, $sql ) or $crase = 1;
		if ($crase === 1) {
			$msg = @pg_last_error ( $this->connection );
			$this->error_msg = "Unable to perform sql: [$sql],server messages:[$msg]";
			return false;
		}
		return @pg_affected_rows ( $this->result );
	}
	
	/**
	 * 表全名,即添加前缀的后的名称
	 * @param string $tablename 表名称
	 */
	public function fullname($table) {
		return $this->prefix . $table;
	}
	
	/**
	 * 最后一次生成的主键值
	 * @return string oid
	 */
	public function last_insert_id($name = '') {
		if ($this->result) {
			return @pg_last_oid ( $this->result );
		}
		return null;
	}
	/**
	 * 查询操作
	 * @param string $sql 要查询的语句
	 * @return ResultSet 查询结果集,失败返回false
	 */
	public function query($sql) {
		$sql = str_replace ( '`', '"', $sql );
		$crash = 0;
		$this->result = $result = @pg_query ( $this->connection, $sql ) or $crash = 1;
		if ($crash === 1) {
			$msg = @pg_last_error ( $this->connection );
			$this->error_msg = "Unable to perform query: [$sql],server messages:[$msg]";
			return false;
		}
		return new PostgresqlResultSet ( $result, $this->connection, $this );
	}
	/**
	 * 分页查询
	 * @param string $sql 语句
	 * @param int $start 分页
	 * @param int $limit 分页大小
	 * @return ResultSet 查询结果集
	 */
	public function queryLimit($sql, $start, $limit) {
		$sql = $sql . ' LIMIT ' . $limit . ' OFFSET ' . ($start * $limit);
		return $this->query ( $sql );
	}
	
	/**
	 * 回滚事务
	 * @return boolean 回滚是否成功
	 */
	public function rollback() {
		if ($this->trans === 0) { //不在事务中
			return true;
		} else {
			if (@pg_query ( $this->connection, "ROLLBACK" ) === true) {
				$this->trans = 0;
				return true;
			} else {
				$msg = @pg_last_error ( $this->connection );
				$this->error_msg = "Unable to rollback current transaction,server messages:[$msg]";
				return false;
			}
		}
	}
	/**
	 * 选择数据库
	 * @param string $db 要选择的数据库
	 * @return boolean 成功true,失败false
	 */
	public function uses($db) {
		return true;
	}
}